import { BaseMode } from "./interface";
import { Utils } from "./util";

let util = new Utils();
export class FunctionTest implements BaseMode{
    run(){
        function add(x: number, y: number): number {
            return x + y;
        }

        let myAdd1 = function(x: number, y: number): number { return x+y; };

        //full function 
        //type defined (x:number, y:number)=>number 
        let myAdd2: (x:number, y:number)=>number =
        function(x: number, y: number): number { return x+y; };

        // option & default parameter
        // has same funtion type
        function buildName(firstName: string = "tanson", lastName?: string) {
            if (lastName)
                return firstName + " " + lastName;
            else
                return firstName;
        }

        let result1 = buildName("Bob");  // works correctly now
        // let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
        let result3 = buildName("Bob", "Adams");  // ah, just right
        let result4 = buildName(undefined, "Adams");  // ah, just right
        // let result5 = buildName(null, "Adams");  // ah, just right
        util.log(result1,"option parameter");
        util.log(result3,"ok parameter");
        util.log(result4,"default parameter");


        //reset parameter
        function buildName2(firstName: string, ...restOfName: string[]) {
            return firstName + " " + restOfName.join(" ");
        }

        let employeeName = buildName2("Joseph", "Samuel", "Lucas", "MacKinzie");
        util.log(employeeName,"reset parameter");


        //this 
        interface Card {
            suit: string;
            card: number;
        }
        interface Deck {
            suits: string[];
            cards: number[];
            createCardPicker(this:Deck): () => Card;
            // [propName:string]:any;
            pickCard(this:Deck) : any;
        }
        let oDesk: Deck = {
            suits: ["hearts", "spades", "clubs", "diamonds"],
            cards: Array(52),
            createCardPicker() {
                // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
                return () => {
                    let pickedCard = Math.floor(Math.random() * 52);
                    let pickedSuit = Math.floor(pickedCard / 13);

                    return {suit: this.suits[pickedSuit], card: pickedCard % 13};
                }
            },
            pickCard(this:Deck):Card{
                let pickedCard = Math.floor(Math.random() * 52);
                let pickedSuit = Math.floor(pickedCard / 13);

                return {suit: this.suits[pickedSuit], card: pickedCard % 13};
            }
        } as Deck;   

        util.log(oDesk.pickCard(),"pickCard");
        let cardPicker = oDesk.createCardPicker();
        let pickedCard = cardPicker();
        util.log(pickedCard,"pickedCard =>");

        //this
        class Element{
            addClickListener(fun:any){

            }
        }
        class Handler {
            info: string;
            //use => function to instend of
            onClickGood = (e: Event) => {
                // oops, used this here. using this callback would crash at runtime
                this.info = e.type;
            };
        }
        let h = new Handler();
        let uiElement = new Element();
        uiElement.addClickListener(h.onClickGood);


        let suits = ["hearts", "spades", "clubs", "diamonds"];
        //make sure the compiler to known the overload function
        function pickCard(x: {suit: string; card: number; }[]): number;
        function pickCard(x: number): {suit: string; card: number; };
        function pickCard(x:any): any {
            // Check to see if we're working with an object/array
            // if so, they gave us the deck and we'll pick the card
            if (typeof x == "object") {
                let pickedCard = Math.floor(Math.random() * x.length);
                return pickedCard;
            }
            // Otherwise just let them pick the card
            else if (typeof x == "number") {
                let pickedSuit = Math.floor(x / 13);
                return { suit: suits[pickedSuit], card: x % 13 };
            }
        }

        let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
        let pickedCard1 = myDeck[pickCard(myDeck)];
        util.log("card: " + pickedCard1.card + " of " + pickedCard1.suit,'pick one random card');

        let pickedCard2 = pickCard(15);
        util.log("card: " + pickedCard2.card + " of " + pickedCard2.suit,"pick assigned card");

    }
}